package jp.ac.waseda.cs.washi.game;

import java.awt.Color;
import java.util.List;

import jp.ac.waseda.cs.washi.game.api.GameInfo;
import jp.ac.waseda.cs.washi.game.api.Player;
import jp.ac.waseda.cs.washi.game.api.PlayerAction;
import jp.ac.waseda.cs.washi.game.entity.Chara;
import jp.ac.waseda.cs.washi.game.entity.GameTime;
import jp.ac.waseda.cs.washi.game.entity.GameTimer;
import jp.ac.waseda.cs.washi.game.entity.Map;
import jp.ac.waseda.cs.washi.game.entity.Pumpkin;
import jp.ac.waseda.cs.washi.game.factory.MapFactory;
import jp.ac.waseda.cs.washi.gameaiarena.gui.Renderer;
import jp.ac.waseda.cs.washi.gameaiarena.runner.AbstractRunner;

public final class GameManager {
	private final GameInfo[] _gameInfos;
	private final Chara[] _charas;
	private final Map _map;
	private final GameTime _time;
	private final GameTimer _timer;
	private final ScoreRenderer _scoreRenderer;

	public GameManager(Renderer render, int charaCount, int mapIndex,
			int roundTime) {
		_charas = new Chara[charaCount];
		_map = MapFactory.createMap(render, _charas, mapIndex);
		_scoreRenderer = new ScoreRenderer(render, _map);
		_time = new GameTime();
		_timer = new GameTimer(_time, roundTime);

		_gameInfos = new GameInfo[2];
		_gameInfos[0] = new GameInfo(_map.getInfo(), _charas[0].getInfo(),
				_charas[1].getInfo(), _timer.getInfo());
		_gameInfos[1] = new GameInfo(_map.getInfo(), _charas[1].getInfo(),
				_charas[0].getInfo(), _timer.getInfo());
	}

	public void initialize(
			List<AbstractRunner<GameInfo, PlayerAction, Player>> players) {
		players.get(0).getPlyaer().initialize(_gameInfos[0]);
		players.get(1).getPlyaer().initialize(_gameInfos[1]);
	}

	public boolean advance(
			List<AbstractRunner<GameInfo, PlayerAction, Player>> players) {
		if (_timer.isOver()) {
			return false;
		}

		for (int i = 0; i < _charas.length; i++) {
			PlayerAction action = players.get(i).run(_gameInfos[i]);
			if (action == null || action == PlayerAction.NONE) {
			} else if (action == PlayerAction.SPELL) {
				MagicManager.spell(_map, _charas[i]);
			} else if (action == PlayerAction.CLEAR) {
				MagicManager.clear(_map, _charas[i]);
			} else {
				MoveManager.moveChara(_map, _charas[i], action.toDirection());
			}
			ScoreManager.updateGameScore(_map, _charas);
		}
		// タイムを進める
		_time.tick();

		return true;
	}

	public boolean advanceForDebug(PlayerAction[] _actions) {
		if (_timer.isOver()) {
			return false;
		}

		for (int i = 0; i < _charas.length; i++) {
			PlayerAction action = _actions[i];
			if (action == null || action == PlayerAction.NONE) {
			} else if (action == PlayerAction.SPELL) {
				MagicManager.spell(_map, _charas[i]);
			} else if (action == PlayerAction.CLEAR) {
				MagicManager.clear(_map, _charas[i]);
			} else {
				MoveManager.moveChara(_map, _charas[i], action.toDirection());
			}
			ScoreManager.updateGameScore(_map, _charas);
		}
		// タイムを進める
		_time.tick();
		return true;
	}

	public Map getMap() {
		return _map;
	}

	public Chara[] getCharas() {
		return _charas;
	}

	public GameTimer getTimer() {
		return _timer;
	}

	public void draw(Renderer render) {
		render.clear(Color.WHITE);
		_map.draw(render);
		for (Chara owner : _charas) {
			for (Pumpkin pump : owner.getPumpkins()) {
				pump.draw(render, owner);
			}
		}
		for (Chara chara : _charas) {
			chara.draw(render, _time);
		}
		_scoreRenderer.drawImage(render, _charas, _time);
	}
}
